<template>
    <div>
        <el-upload action :auto-upload="false" :show-file-list="false" :on-change="changeFile">
            <el-button size="small" type="primary">选择文件</el-button>
            <div slot="tip" class="el-upload__tip">
                1.上传文件不超过5G<br />2.只能上传一个文件<br />3.等待进度条出现√才是上传完成
            </div>
        </el-upload>
        <!-- PROGRESS -->
        <div class="progress">
            <span>上传进度：{{ total | totalText }}%</span>
            <el-link type="primary" v-if="total > 0 && total < 100" @click="handleBtn">{{ btn | btnText }}</el-link>
        </div>
    </div>
</template>

<script>
import SparkMD5 from "spark-md5";
import { fileParse, getFileMd5 } from "../js/fileParse/index";
import axios from "axios";
export default {
    data() {
        return {
            total: 0,
            btn: false,
            abort: false,
            uploadSuc: false,
            slicesNum: null,
            chunkNumber: null,
            issueId: 40293,
            singlePartSize: 1024 * 1024 * 100,
            userInfo: {
                userName: 'admin',
                userId: 'admin',
            },
        };
    },
    filters: {
        btnText(btn) {
            return btn ? "继续" : "暂停";
        },
        totalText(total) {
            return total > 100 ? 100 : total;
        },
    },
    methods: {
        // 分片上传
        async changeFile(file) {
            if (!file) return;
            file = file.raw;
            this.total = 0;
            this.abort = false;
            this.btn = false;

            console.log(file, "file");

            let hash = await getFileMd5(file, this.singlePartSize);
            let suffix = /\.([0-9a-zA-Z]+)$/i.exec(file.name)[1];

            // 切片个数
            let spliceTemp = Math.floor(file.size / this.singlePartSize)
            this.slicesNum = file.size % this.singlePartSize > 0 ? spliceTemp + 1 : spliceTemp;

            console.log("hash " + hash + " suffix " + suffix + " slicesNum " + this.slicesNum);

            // 创建切片
            let partList = [];
            let cur = 0;

            for (let i = 0; i < this.slicesNum; i++) {
                let splitEndIdx = Math.min(cur + this.singlePartSize, file.size);
                let item = {
                    filename: `${hash}_${i}.${suffix}`,
                    chunkNumber: `${i}`,
                    file: file.slice(cur, splitEndIdx)
                };
                console.log(cur)
                console.log(item)
                cur = splitEndIdx;
                partList.push(item);
            }
            this.requestData = {
                fileMd5: hash,
                name: file.name,
                size: file.size,
                totalChunks: this.slicesNum,
                issueId: this.issueId,
                uname: this.userInfo.userName,
                singlePartSize: this.singlePartSize
            };
            this.partList = partList;

            console.log(partList);

            this.sendRequest();
        },
        async sendRequest() {
            this.uploadSuc = false;
            let requestList = [];

            this.partList.forEach((item, index) => {
                // 每一个函数都发送一个切片请求
                let fn = async (chunkNumber) => {
                    let formData = new FormData(),
                        shardFile = new SparkMD5.ArrayBuffer(),
                        shardFileBuffer = await fileParse(item.file, "buffer"),
                        shardFileHash;
                    shardFile.append(shardFileBuffer);
                    shardFileHash = shardFile.end();
                    formData.append(
                        "chunkNumber",
                        chunkNumber ? chunkNumber : item.chunkNumber
                    );
                    formData.append("id", this.requestData.issueId);
                    formData.append("chunks", this.slicesNum);
                    formData.append("chunk", index);
                    formData.append("name", this.requestData.name);
                    formData.append("chunkSize", this.requestData.singlePartSize);
                    formData.append("file", item.file);
                    formData.append("md5", this.requestData.fileMd5);
                    formData.append("totalChunks", this.requestData.totalChunks);
                    formData.append("size", item.file.size);
                    return axios
                        .post(
                            "http://localhost:8082/common/sliceUpload/upload",
                            formData,
                            {
                                headers: { "Content-Type": "multipart/form-data", "domainAccount": this.requestData.uname },
                            }
                        )
                        .then((res) => {
                            console.log(res);
                            const { uploadComplete, code } = res.data;
                            if (!uploadComplete) {
                                if (code === 206) {
                                    this.total += parseInt(100 / this.slicesNum);
                                    // 传完的切片我们把它移除掉
                                    if (chunkNumber) {
                                        this.partList.splice(index - 1, 1);
                                    }
                                    return index;
                                } else {
                                    // TODO 胡航，这里想个办法让它不要继续上传
                                    this.uploadSuc = false;
                                }
                            } else {
                                this.uploadSuc = true;
                            }
                        });
                };
                requestList.push(fn);
            });

            let i = 0;

            let send = async () => {
                if (this.abort) return;
                if (i >= requestList.length && !this.uploadSuc) {
                    this.$message.warning("上传失败,请重新上传");
                    this.total = 0;
                    return;
                }
                if (this.uploadSuc) {
                    this.$message.success("上传成功");
                    this.total = 100;
                    return;
                }

                await requestList[i](this.chunkNumber).then((res) => {
                    this.chunkNumber = res;
                });

                i++;
                send();
            };
            send();
        },
        handleBtn() {
            if (this.btn) {
                this.abort = false;
                this.btn = false;
                this.sendRequest();
                return;
            }

            this.btn = true;
            this.abort = true;
        },
    },
};
</script>
